package com.feng.fengDUtil;


import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.*;

public abstract class MyAnnotationUtils {
    static final String VALUE = "value";
    private static final Map<Class<?>, Boolean> annotatedInterfaceCache = new WeakHashMap();

    public MyAnnotationUtils() {
    }

    public static <T extends Annotation> T getAnnotation(AnnotatedElement ae, Class<T> annotationType) {
        T ann = ae.getAnnotation(annotationType);
        if (ann == null) {
            Annotation[] arr$ = ae.getAnnotations();
            int len$ = arr$.length;

            for(int i$ = 0; i$ < len$; ++i$) {
                Annotation metaAnn = arr$[i$];
                ann = metaAnn.annotationType().getAnnotation(annotationType);
                if (ann != null) {
                    break;
                }
            }
        }

        return ann;
    }

    public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
        A annotation = getAnnotation(method, annotationType);
        Class<?> cl = method.getDeclaringClass();
        if (annotation == null) {
            annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());
        }

        while(annotation == null) {
            cl = cl.getSuperclass();
            if (cl == null || cl == Object.class) {
                break;
            }

            try {
                Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes());
                annotation = getAnnotation(equivalentMethod, annotationType);
                if (annotation == null) {
                    annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());
                }
            } catch (NoSuchMethodException var5) {
                ;
            }
        }

        return annotation;
    }

    private static <A extends Annotation> A searchOnInterfaces(Method method, Class<A> annotationType, Class<?>[] ifcs) {
        A annotation = null;
        Class[] arr$ = ifcs;
        int len$ = ifcs.length;

        for(int i$ = 0; i$ < len$; ++i$) {
            Class<?> iface = arr$[i$];
            if (isInterfaceWithAnnotatedMethods(iface)) {
                try {
                    Method equivalentMethod = iface.getMethod(method.getName(), method.getParameterTypes());
                    annotation = getAnnotation(equivalentMethod, annotationType);
                } catch (NoSuchMethodException var9) {
                    ;
                }

                if (annotation != null) {
                    break;
                }
            }
        }

        return annotation;
    }

    private static boolean isInterfaceWithAnnotatedMethods(Class<?> iface) {
        Map var1 = annotatedInterfaceCache;
        synchronized(annotatedInterfaceCache) {
            Boolean flag = (Boolean)annotatedInterfaceCache.get(iface);
            if (flag != null) {
                return flag.booleanValue();
            } else {
                boolean found = false;
                Method[] arr$ = iface.getMethods();
                int len$ = arr$.length;

                for(int i$ = 0; i$ < len$; ++i$) {
                    Method ifcMethod = arr$[i$];
                    if (ifcMethod.getAnnotations().length > 0) {
                        found = true;
                        break;
                    }
                }

                annotatedInterfaceCache.put(iface, found);
                return found;
            }
        }
    }

    public static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType) {
        A annotation = clazz.getAnnotation(annotationType);
        if (annotation != null) {
            return annotation;
        } else {
            Class[] arr$ = clazz.getInterfaces();
            int len$ = arr$.length;

            int i$;
            for(i$ = 0; i$ < len$; ++i$) {
                Class<?> ifc = arr$[i$];
                annotation = findAnnotation(ifc, annotationType);
                if (annotation != null) {
                    return annotation;
                }
            }

            if (!Annotation.class.isAssignableFrom(clazz)) {
                Annotation[] annotations = clazz.getAnnotations();
                len$ = annotations.length;

                for(i$ = 0; i$ < len$; ++i$) {
                    Annotation ann = annotations[i$];
                    annotation = findAnnotation(ann.annotationType(), annotationType);
                    if (annotation != null) {
                        return annotation;
                    }
                }
            }

            Class<?> superClass = clazz.getSuperclass();
            return superClass != null && superClass != Object.class ? findAnnotation(superClass, annotationType) : null;
        }
    }

    public static Class<?> findAnnotationDeclaringClass(Class<? extends Annotation> annotationType, Class<?> clazz) {
        if (clazz != null && !clazz.equals(Object.class)) {
            return isAnnotationDeclaredLocally(annotationType, clazz) ? clazz : findAnnotationDeclaringClass(annotationType, clazz.getSuperclass());
        } else {
            return null;
        }
    }

    public static boolean isAnnotationDeclaredLocally(Class<? extends Annotation> annotationType, Class<?> clazz) {
        boolean declaredLocally = false;
        Iterator i$ = Arrays.asList(clazz.getDeclaredAnnotations()).iterator();

        while(i$.hasNext()) {
            Annotation annotation = (Annotation)i$.next();
            if (annotation.annotationType().equals(annotationType)) {
                declaredLocally = true;
                break;
            }
        }

        return declaredLocally;
    }

    public static boolean isAnnotationInherited(Class<? extends Annotation> annotationType, Class<?> clazz) {
        return clazz.isAnnotationPresent(annotationType) && !isAnnotationDeclaredLocally(annotationType, clazz);
    }

    public static Map<String, Object> getAnnotationAttributes(Annotation annotation) {
        return getAnnotationAttributes(annotation, false);
    }

    public static Map<String, Object> getAnnotationAttributes(Annotation annotation, boolean classValuesAsString) {
        Map<String, Object> attrs = new HashMap();
        Method[] methods = annotation.annotationType().getDeclaredMethods();
        Method[] arr$ = methods;
        int len$ = methods.length;

        for(int i$ = 0; i$ < len$; ++i$) {
            Method method = arr$[i$];
            if (method.getParameterTypes().length == 0 && method.getReturnType() != Void.TYPE) {
                try {
                    Object value = method.invoke(annotation);
                    if (classValuesAsString) {
                        if (value instanceof Class) {
                            value = ((Class)value).getName();
                        } else if (value instanceof Class[]) {
                            Class<?>[] clazzArray = (Class[])((Class[])value);
                            String[] newValue = new String[clazzArray.length];

                            for(int i = 0; i < clazzArray.length; ++i) {
                                newValue[i] = clazzArray[i].getName();
                            }

                            value = newValue;
                        }
                    }

                    attrs.put(method.getName(), value);
                } catch (Exception var12) {
                    throw new IllegalStateException("Could not obtain annotation attribute values", var12);
                }
            }
        }

        return attrs;
    }

    public static Object getValue(Annotation annotation) {
        return getValue(annotation, "value");
    }

    public static Object getValue(Annotation annotation, String attributeName) {
        try {
            Method method = annotation.annotationType().getDeclaredMethod(attributeName);
            return method.invoke(annotation);
        } catch (Exception var3) {
            return null;
        }
    }

    public static Object getDefaultValue(Annotation annotation) {
        return getDefaultValue(annotation, "value");
    }

    public static Object getDefaultValue(Annotation annotation, String attributeName) {
        return getDefaultValue(annotation.annotationType(), attributeName);
    }

    public static Object getDefaultValue(Class<? extends Annotation> annotationType) {
        return getDefaultValue(annotationType, "value");
    }

    public static Object getDefaultValue(Class<? extends Annotation> annotationType, String attributeName) {
        try {
            Method method = annotationType.getDeclaredMethod(attributeName);
            return method.getDefaultValue();
        } catch (Exception var3) {
            return null;
        }
    }
}
